package com.glodon.async.controller;

import com.alibaba.fastjson.JSONObject;
import com.glodon.async.service.UserBatchService;
import com.glodon.async.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.Callable;

/**
 * @Author: lilin
 * @Date: 2022/8/10
 */
@RestController
@RequestMapping("/mine")
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private UserBatchService userBatchService;

    /**
     * 1.传统代码逻辑-串行
     * @param userId 用户id
     * 存在问题：随着APP展示业务增多，导致调用越来越多的系统，响应时间变长
     */
    @GetMapping("/getUserInfo/{userId}")
    public JSONObject getUserInfo(@PathVariable String userId){
        long start = System.currentTimeMillis();

        JSONObject userInfo = userService.getUserInfo(userId);

        long end = System.currentTimeMillis();
        System.out.println("传统代码逻辑耗时：" + (end - start) + "ms");

        return userInfo;
    }


    /**
     * 2.多线程调用-并行
     * @param userId 用户id
     * 存在问题：调用多个系统时，若其中某个系统响应时间长，导致Tomcat线程会阻塞，从而导致服务器吞吐量下降
     */
    @GetMapping("/getUserInfoAsync/{userId}")
    public JSONObject getUserInfoAsync(@PathVariable String userId){
        long start = System.currentTimeMillis();

        JSONObject userInfo = userService.getUserInfoAsync(userId);

        long end = System.currentTimeMillis();
        System.out.println("多线程调用：" + (end - start) + "ms");
        return userInfo;
    }


    /**
     * 3.Servlet3.0异步处理请求
     * @param userId 用户id
     * 中文网：https://www.w3cschool.cn/spring_mvc_documentation_linesh_translation/spring_mvc_documentation_linesh_translation-oxmy27rf.html
     * 官网：https://docs.spring.io/spring-framework/docs/5.2.5.RELEASE/spring-framework-reference/web.html#mvc-ann-async
     * 存在问题：吞吐量提高了，但是后端服务压力增高了
     */
    @GetMapping("/getUserInfoCall/{userId}")
    public Callable<JSONObject> getUserInfoCall(@PathVariable String userId){
        long tomcatStart = System.currentTimeMillis();

        Callable<JSONObject> callable = new Callable<JSONObject>() {
            @Override
            public JSONObject call() throws Exception {
                long childStart = System.currentTimeMillis();
                JSONObject userInfoAsync = userService.getUserInfoAsync(userId);
                long childEnd = System.currentTimeMillis();
                System.out.println("Child子线程-" + Thread.currentThread().getName() + "，耗时：" + (childEnd - childStart) + "ms");
                return userInfoAsync;
            }
        };

        long tomcatEnd = System.currentTimeMillis();
        System.out.println("Tomcat主线程-" + Thread.currentThread().getName() + "，耗时：" + (tomcatEnd - tomcatStart) + "ms");
        return callable;
    }


    /**
     * 4.最终解决方案：多线程 + Servlet3.0异步 + 定时线程池 + 队列 + CompletableFuture
     * @param userId
     * @return
     */
    @GetMapping("/getUserInfoBatch/{userId}")
    public Callable<JSONObject> getUserInfoBatch(@PathVariable String userId){

        Callable<JSONObject> callable = new Callable<JSONObject>() {
            @Override
            public JSONObject call() throws Exception {
                JSONObject userInfoAsync = userBatchService.getUserInfoBatch(userId);
                return userInfoAsync;
            }
        };

        return callable;
    }


}
